package com.gmstu.springframework.mvc.servlet;

import com.gmstu.mvcservlet.annotation.GpRequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @author John.zhang
 * @version Id: GpHandlerAdapter, v 1.0 2020/8/22 21:39 ZhiYong Exp $
 */
class GpHandlerAdapter {

    boolean supports(Object handler) {
        return handler instanceof GpHandlerMapping;
    }

    GpModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        GpHandlerMapping handlerMapping = (GpHandlerMapping) handler;

        Annotation[][] pa = handlerMapping.getMethod().getParameterAnnotations();

        Map<String, Integer> paramIndexMapping = new HashMap<String, Integer>(pa.length);
        for (int i = 0; i < pa.length; i++) {
            for (Annotation annotation : pa[i]) {
                if (annotation instanceof GpRequestMapping) {
                    String paramName = ((GpRequestMapping) annotation).value();
                    if (!"".equals(paramName.trim())) {
                        paramIndexMapping.put(paramName, i);
                    }
                }
            }
        }

        Class<?>[] parameterTypes = handlerMapping.getMethod().getParameterTypes();
        for (int i = 0; i < parameterTypes.length; i++) {
            Class<?> parameterType = parameterTypes[i];
            if (parameterType == HttpServletRequest.class || parameterType == HttpServletResponse.class) {
                paramIndexMapping.put(parameterType.getName(), i);
            }
        }

        //形参
        Map<String, String[]> params = request.getParameterMap();
        //实参
        Object[] paramValues = new Object[parameterTypes.length];

        for (Map.Entry<String, String[]> param : params.entrySet()) {
            String value = Arrays.toString(param.getValue()).replace("\\[|\\]", "").replace("\\s", ",");

            if (!paramIndexMapping.containsKey(param.getKey())) {
                continue;
            }
            Integer index = paramIndexMapping.get(param.getKey());
            //paramIndexMapping和parameterTypes顺序同为一个method
            paramValues[index] = caseStringValue(value, parameterTypes[index]);
        }

        if (paramIndexMapping.containsKey(HttpServletRequest.class.getName())) {
            int reqIndex = paramIndexMapping.get(HttpServletRequest.class.getName());
            paramValues[reqIndex] = request;
        }

        if (paramIndexMapping.containsKey(HttpServletResponse.class.getName())) {
            int respIndex = paramIndexMapping.get(HttpServletResponse.class.getName());
            paramValues[respIndex] = response;
        }

        Object result = handlerMapping.getMethod().invoke(handlerMapping.getController(), paramValues);
        if (result == null || result instanceof Void) {
            return null;
        }
        boolean isModelAndView = handlerMapping.getMethod().getReturnType() == GpModelAndView.class;
        if (isModelAndView) {
            return (GpModelAndView) result;
        }
        return null;
    }

    private Object caseStringValue(String value, Class<?> parameterType) {
        if (String.class == parameterType) {
            return value;
        }
        if (Integer.class == parameterType) {
            return Integer.valueOf(value);
        } else {
            if (value != null) {
                return value;
            }
            return null;
        }
    }

}
